using System;
// define float as Scalar
using Scalar = System.Single;

namespace OhioState.Math
{
    #region Vector
    //
    // Vector 
    //
    [Serializable]
    public class Vector : IVector
    {
        // data member
        protected Scalar[] _vector;

        // property
        public Scalar this[int index]
        {
            get { return _vector[index]; }
            set
            {
                _vector[index] = value;
            }
        }

        internal Scalar[] InternalVector
        {
            get { return this._vector; }
            set { this._vector = value; }
        }

        public Scalar x
        {
            get { return _vector[0]; }
            set { _vector[0] = value; }
        }
        public Scalar y
        {
            get { return _vector[1]; }
            set { _vector[1] = value; }
        }

        public Scalar z
        {
            get { return _vector[2]; }
            set { _vector[2] = value; }
        }

        public Scalar w
        {
            get { return _vector[3]; }
            set { _vector[3] = value; }
        }

        // public methods

        public void Zero()
        {
            for (int i = 0; i < _vector.Length; i++)
            {
                _vector[i] = (Scalar)0.0;
            }
        }

        public void negate()
        {
            for (int i = 0; i < _vector.Length; i++)
            {
                _vector[i] = -_vector[i];
            }
        }

        public Scalar Length()
        {
            return (Scalar)System.Math.Sqrt((double)this.LengthSquared());
        }

        public Scalar LengthSquared()
        {
            Scalar r = 0;
            for (int i = 0; i < _vector.Length; i++)
            {
                r += _vector[i] * _vector[i];
            }
            return r;
        }

        public Scalar dot(Vector v)
        {
            return dot(this,v);
        }

        public static Scalar dot(Vector v1, Vector v2)
        {
            Scalar r = 0;
            for (int i = 0; i < v1._vector.Length; i++)
            {
                r += v1._vector[i] * v2._vector[i];
            }
            return r;
        }

        public void normalize()
        {
            Scalar len = Length();
            for (int i = 0; i < _vector.Length; i++)
            {
                _vector[i] /= len;
            }
        }

        public void print()
        {
            string content = "[ ";
            for (int i = 0; i < _vector.Length; i++)
            {
                content = content + _vector[i] + " ";
            }
            content = content + "]\n";
            Console.WriteLine(content);
        }

        public override int GetHashCode()
        {
            return _vector.GetHashCode();
        }
    }

    #endregion

    #region Vector2
    
    /// <summary>
    /// Two dimensional Vector class
    /// </summary>
    [Serializable]
    public class Vector2 : Vector
    {
        #region Constructors
        public Vector2()
        {
            _vector = new Scalar[2];
            Zero();
        }

        public Vector2(Scalar[] t)
        {
            _vector = new Scalar[2];
            _vector[0] = t[0];
            _vector[1] = t[1];
        }

        public Vector2(Vector2 v)
        {
            _vector = new Scalar[2];
            _vector[0] = v._vector[0];
            _vector[1] = v._vector[1];
        }

        public Vector2(Scalar x, Scalar y)
        {
            _vector = new Scalar[2];
            _vector[0] = x;
            _vector[1] = y;
        }
        #endregion

        /// <summary>
        /// Constructor for Vector2
        /// </summary>
        /// <returns>array of scalars</returns>
        public Scalar[] getValue()
        {
            Scalar[] rs = new Scalar[2];
            rs[0] = _vector[0];
            rs[1] = _vector[1];

            return rs;
        }
        /// <summary>
        /// Sets a Vector2
        /// </summary>
        /// <param name="v0">first component</param>
        /// <param name="v1">second component</param>
        public void setValue(Scalar v0, Scalar v1)
        {
            _vector[0] = v0;
            _vector[1] = v1;
        }

        /// <summary>
        /// Dot product of 2 Vector2 vectors
        /// </summary>
        /// <param name="v1">first vector</param>
        /// <param name="v2">second vector</param>
        /// <returns>dot product of v1 and v2</returns>
        public static Scalar dot(Vector2 v1, Vector2 v2)
        {
            Scalar r;
            r = v1._vector[0] * v2._vector[0] + v1._vector[1] * v2._vector[1] + v1._vector[2] * v2._vector[2];
            return r;
        }

        /// <summary>
        /// Normalize a Vector2
        /// </summary>
        /// <param name="v">input Vector2</param>
        /// <returns>normalized v</returns>
        public static Vector2 normalize(Vector2 v)
        {
            Vector2 rv = new Vector2();
            Scalar len = v.Length();
            rv._vector[0] = v._vector[0] /= len;
            rv._vector[1] = v._vector[1] /= len;
            return rv;
        }

        /// <summary>
        /// Cross product of two Vector2
        /// </summary>
        /// <param name="rhs">input Vector2</param>
        /// <returns>Cross product of this and rhs</returns>
        public Scalar cross(Vector2 rhs)
        {
            Scalar rv;
            rv = _vector[0] * rhs._vector[1] - _vector[1] * rhs._vector[0];
            return rv;
        }


        #region Operator overloads
        public static Vector2 operator +(Vector2 a, Vector2 b)
        {
            Vector2 temp = new Vector2();
            temp._vector[0] = a._vector[0] + b._vector[0];
            temp._vector[1] = a._vector[1] + b._vector[1];
            return temp;
        }

        public static Vector2 operator -(Vector2 v)
        {
            Vector2 temp = new Vector2();
            temp._vector[0] = -v._vector[0];
            temp._vector[1] = -v._vector[1];
            return temp;
        }

        public static Vector2 operator -(Vector2 a, Vector2 b)
        {
            Vector2 temp = new Vector2();
            temp._vector[0] = a._vector[0] - b._vector[0];
            temp._vector[1] = a._vector[1] - b._vector[1];
            return temp;
        }

        public static Vector2 operator *(Vector2 a, Vector2 b)
        {
            Vector2 temp = new Vector2();
            temp._vector[0] = a._vector[0] * b._vector[0];
            temp._vector[1] = a._vector[1] * b._vector[1];
            return temp;
        }

        public static Vector2 operator *(Scalar s, Vector2 b)
        {
            Vector2 temp = new Vector2();
            temp._vector[0] = s * b._vector[0];
            temp._vector[1] = s * b._vector[1];
            return temp;
        }

        public static Vector2 operator *(Vector2 a, Scalar s)
        {
            Vector2 temp = new Vector2();
            temp._vector[0] = a._vector[0] * s;
            temp._vector[1] = a._vector[1] * s;
            return temp;
        }

        public static Vector2 operator /(Vector2 a, Vector2 b)
        {
            Vector2 temp = new Vector2();
            temp._vector[0] = a._vector[0] / b._vector[0];
            temp._vector[1] = a._vector[1] / b._vector[1];
            return temp;
        }

        public static Vector2 operator /(Scalar s, Vector2 b)
        {
            Vector2 temp = new Vector2();
            temp._vector[0] = s / b._vector[0];
            temp._vector[1] = s / b._vector[1];
            return temp;
        }

        public static Vector2 operator /(Vector2 a, Scalar s)
        {
            Vector2 temp = new Vector2();
            temp._vector[0] = a._vector[0] / s;
            temp._vector[1] = a._vector[1] / s;
            return temp;
        }

        public static bool operator ==(Vector2 a, Vector2 b)
        {
            if (a._vector[0] != b._vector[0]) return false;
            if (a._vector[1] != b._vector[1]) return false;
            return true;
        }

        public static bool operator !=(Vector2 a, Vector2 b)
        {
            return !(a == b);
        }
        #endregion
        /// <summary>
        /// Check for equality of an object with this object
        /// </summary>
        /// <param name="obj">input obj</param>
        /// <returns>true or false</returns>
        public override bool Equals(Object obj)
        {
            return obj is Vector2 && this == (Vector2)obj;
        }
    }

    #endregion

    #region Vector3

    //
    // Vector3 
    //
    [Serializable]
    public class Vector3: IVector
    {
        // data member
        private Scalar[] _vector3 = new Scalar[3];

        #region Constructors
        public Vector3()
        {
            Zero();
        }

        public Vector3(Scalar[] t)
        {
            _vector3[0] = t[0];
            _vector3[1] = t[1];
            _vector3[2] = t[2];
        }

        public Vector3(Vector3 v)
        {
            _vector3[0] = v._Vector3[0];
            _vector3[1] = v._Vector3[1];
            _vector3[2] = v._Vector3[2];
        }

        public Vector3(Scalar x, Scalar y, Scalar z)
        {
            _vector3[0] = x;
            _vector3[1] = y;
            _vector3[2] = z;
        }
        #endregion

        // property
        public Scalar[] _Vector3
        {
            get { return this._vector3; }
            set { this._vector3 = value; }
        }

        public Scalar this[int index]
        {
            get { return _vector3[index]; }
            set
            {
                if ((index >= 0) && (index < 3))
                    _vector3[index] = value;
                else
                    throw (new IndexOutOfRangeException());
            }
        }

        public Scalar x
        {
            get { return _vector3[0]; }
            set { _vector3[0] = value; }
        }
        public Scalar y
        {
            get { return _vector3[1]; }
            set { _vector3[1] = value; }
        }
        public Scalar z
        {
            get { return _vector3[2]; }
            set { _vector3[2] = value; }
        }

        // public methods
        public Scalar[] getValue()
        {
            Scalar[] rs = new Scalar[3];
            rs[0] = _vector3[0];
            rs[1] = _vector3[1];
            rs[2] = _vector3[2];

            return rs;
        }

		public void setValue(Scalar v0, Scalar v1, Scalar v2)
		{
			_vector3[0] = v0;
			_vector3[1] = v1;
			_vector3[2] = v2;
		}

        public void Zero()
        {
            _vector3[0] = 0.0F;
            _vector3[1] = 0.0F;
            _vector3[2] = 0.0F;
        }

        public void negate()
        {
            _vector3[0] = -_vector3[0];
            _vector3[1] = -_vector3[1];
            _vector3[2] = -_vector3[2];
        }

        public void absoluteValue()
        {
            _vector3[0] = (_vector3[0] < 0.0) ? -_vector3[0] : _vector3[0];
            _vector3[1] = (_vector3[1] < 0.0) ? -_vector3[1] : _vector3[1];
            _vector3[2] = (_vector3[2] < 0.0) ? -_vector3[2] : _vector3[2];
        }

        public Scalar Length()
        {
            Scalar r;
            r = _vector3[0] * _vector3[0] + _vector3[1] * _vector3[1] + _vector3[2] * _vector3[2];
            return (Scalar)System.Math.Sqrt((double)r);
        }

        public Scalar LengthSquared()
        {
            Scalar r;
            r = _vector3[0] * _vector3[0] + _vector3[1] * _vector3[1] + _vector3[2] * _vector3[2];
            return r;
        }

        public Scalar dot(Vector3 v)
        {
            Scalar r;
            r = _vector3[0] * v._Vector3[0] + _vector3[1] * v._Vector3[1] + _vector3[2] * v._Vector3[2];
            return r;
        }

        public static Scalar dot(Vector3 v1, Vector3 v2)
        {
            Scalar r;
            r = v1._Vector3[0] * v2._Vector3[0] + v1._Vector3[1] * v2._Vector3[1] + v1._Vector3[2] * v2._Vector3[2];
            return r;
        }

        public void normalize()
        {
            Scalar len = Length();
            _vector3[0] /= len;
            _vector3[1] /= len;
            _vector3[2] /= len;
        }

        public static Vector3 normalize(Vector3 v)
        {
            Vector3 rv = new Vector3();
            Scalar len = v.Length();
            rv._Vector3[0] = v._Vector3[0] /= len;
            rv._Vector3[1] = v._Vector3[1] /= len;
            rv._Vector3[2] = v._Vector3[2] /= len;
            return rv;
        }

        public Vector3 cross(Vector3 rhs)
        {
            Vector3 rv = new Vector3();
            rv._Vector3[0] = _vector3[1] * rhs._Vector3[2] - _vector3[2] * rhs._Vector3[1];
            rv._Vector3[1] = _vector3[2] * rhs._Vector3[0] - _vector3[0] * rhs._Vector3[2];
            rv._Vector3[2] = _vector3[0] * rhs._Vector3[1] - _vector3[1] * rhs._Vector3[0];
            return rv;
        }


        public void print()
        {
            string content = "[ ";
            content = content + _vector3[0] + " " + _vector3[1] + " "
                      + _vector3[2] + " ]\n";
            Console.WriteLine(content);
        }

        // operator functions
        public static Vector3 operator +(Vector3 a, Vector3 b)
        {
            Vector3 temp = new Vector3();
            temp._Vector3[0] = a._Vector3[0] + b._Vector3[0];
            temp._Vector3[1] = a._Vector3[1] + b._Vector3[1];
            temp._Vector3[2] = a._Vector3[2] + b._Vector3[2];
            return temp;   
        }

        public static Vector3 operator -(Vector3 v)
        {
            Vector3 temp = new Vector3();
            temp._Vector3[0] = -v._Vector3[0];
            temp._Vector3[1] = -v._Vector3[1];
            temp._Vector3[2] = -v._Vector3[2];
            return temp;
        }

        public static Vector3 operator -(Vector3 a, Vector3 b)
        {
            Vector3 temp = new Vector3();
            temp._Vector3[0] = a._Vector3[0] - b._Vector3[0];
            temp._Vector3[1] = a._Vector3[1] - b._Vector3[1];
            temp._Vector3[2] = a._Vector3[2] - b._Vector3[2];
            return temp;
        }

        public static Vector3 operator *(Vector3 a, Vector3 b)
        {
            Vector3 temp = new Vector3();
            temp._Vector3[0] = a._Vector3[0] * b._Vector3[0];
            temp._Vector3[1] = a._Vector3[1] * b._Vector3[1];
            temp._Vector3[2] = a._Vector3[2] * b._Vector3[2];
            return temp;
        }

        public static Vector3 operator *(Scalar s, Vector3 b)
        {
            Vector3 temp = new Vector3();
            temp._Vector3[0] = s * b._Vector3[0];
            temp._Vector3[1] = s * b._Vector3[1];
            temp._Vector3[2] = s * b._Vector3[2];
            return temp;
        }

        public static Vector3 operator *(Vector3 a, Scalar s)
        {
            Vector3 temp = new Vector3();
            temp._Vector3[0] = a._Vector3[0] * s;
            temp._Vector3[1] = a._Vector3[1] * s;
            temp._Vector3[2] = a._Vector3[2] * s;
            return temp;
        }

        public static Vector3 operator /(Vector3 a, Vector3 b)
        {
            Vector3 temp = new Vector3();
            temp._Vector3[0] = a._Vector3[0] / b._Vector3[0];
            temp._Vector3[1] = a._Vector3[1] / b._Vector3[1];
            temp._Vector3[2] = a._Vector3[2] / b._Vector3[2];
            return temp;
        }

        public static Vector3 operator /(Scalar s, Vector3 b)
        {
            Vector3 temp = new Vector3();
            temp._Vector3[0] = s / b._Vector3[0];
            temp._Vector3[1] = s / b._Vector3[1];
            temp._Vector3[2] = s / b._Vector3[2];
            return temp;
        }

        public static Vector3 operator /(Vector3 a, Scalar s)
        {
            Vector3 temp = new Vector3();
            temp._Vector3[0] = a._Vector3[0] / s;
            temp._Vector3[1] = a._Vector3[1] / s;
            temp._Vector3[2] = a._Vector3[2] / s;
            return temp;
        }

        public static bool operator == (Vector3 a, Vector3 b)
        {
            if(a._Vector3[0] != b._Vector3[0]) return false;
            if (a._Vector3[1] != b._Vector3[1]) return false;
            if (a._Vector3[2] != b._Vector3[2]) return false;
            return true;
        }

        public static bool operator !=(Vector3 a, Vector3 b)
        {
            return !(a == b);
        }

        public override bool Equals(Object obj)
        {
            return obj is Vector3 && this == (Vector3)obj;
        }

        public override int GetHashCode()
        {
            return _vector3.GetHashCode();
        }
    }

    #endregion

    #region Vector4
    //
    // Vector4
    //
    [Serializable]
    public class Vector4 : IVector
    {
        // data memeber
        private Scalar[] _vector4 = new Scalar[4];

        #region Constructors
        public Vector4() 
        {
            Zero();
        }

        public Vector4(Scalar[] t) 
        {
            _vector4[0] = t[0];
            _vector4[1] = t[1];
            _vector4[2] = t[2];
            _vector4[3] = t[3];
        }

        public Vector4(Vector4 v)
        {
            _vector4[0] = v._Vector4[0];
            _vector4[1] = v._Vector4[1];
            _vector4[2] = v._Vector4[2];
            _vector4[3] = v._Vector4[3];
        }

        public Vector4(Scalar x, Scalar y, Scalar z, Scalar w)
        {
            _vector4[0] = x;
            _vector4[1] = y;
            _vector4[2] = z;
            _vector4[3] = w;
        }

        public Vector4(Vector3 v, Scalar w)
        {
            _vector4[0] = v._Vector3[0];
            _vector4[1] = v._Vector3[1];
            _vector4[2] = v._Vector3[2];
            _vector4[3] = w;
        }
        #endregion

        // property
        public Scalar[] _Vector4
        {
            get { return this._vector4; }
            set { this._vector4 = value; }
        }

        public Scalar this[int index]
        {
            get { return _vector4[index]; }
            set
            {
                if ((index >= 0) && (index < 4))
                    _vector4[index] = value;
                else
                    throw (new IndexOutOfRangeException());
            }
        }

        public Scalar x
        {
            get { return _vector4[0]; }
            set { _vector4[0] = value; }
        }
        public Scalar y
        {
            get { return _vector4[1]; }
            set { _vector4[1] = value; }
        }
        public Scalar z
        {
            get { return _vector4[2]; }
            set { _vector4[2] = value; }
        }
        public Scalar w
        {
            get { return _vector4[3]; }
            set { _vector4[3] = value; }
        }

        // public methods
        public Scalar[] getValue()
        {
            Scalar[] rs = new Scalar[4];
            rs[0] = _vector4[0];
            rs[1] = _vector4[1];
            rs[2] = _vector4[2];
            rs[3] = _vector4[3];

            return rs;
        }

        public void Zero()
        {
            _vector4[0] = 0.0F;
            _vector4[1] = 0.0F;
            _vector4[2] = 0.0F;
            _vector4[3] = 0.0F;
        }

        public void negate()
        {
            _vector4[0] = -_vector4[0];
            _vector4[1] = -_vector4[1];
            _vector4[2] = -_vector4[2];
            _vector4[3] = -_vector4[3];
        }

        public Scalar Length()
        {
            Scalar r;
            r = _vector4[0] * _vector4[0] + _vector4[1] * _vector4[1] + 
                _vector4[2] * _vector4[2] + _vector4[3] * _vector4[3];
            return (Scalar)System.Math.Sqrt((double)r);
        }

        public Scalar LengthSquared()
        {
            Scalar r;
            r = _vector4[0] * _vector4[0] + _vector4[1] * _vector4[1] +
                _vector4[2] * _vector4[2] + _vector4[3] * _vector4[3];
            return r;
        }

        public Scalar dot(Vector4 v)
        {
            Scalar r;
            r = _vector4[0] * v._Vector4[0] + _vector4[1] * v._Vector4[1] +
                _vector4[2] * v._Vector4[2] + _vector4[3] * v._Vector4[3];
            return r;
        }

        public static Scalar dot(Vector4 v1, Vector4 v2)
        {
            Scalar r;
            r = v1._Vector4[0] * v2._Vector4[0] + v1._Vector4[1] * v2._Vector4[1] +
                v1._Vector4[2] * v2._Vector4[2] + v1._Vector4[3] * v2._Vector4[3];
            return r;
        }

        public void normalize()
        {
            Scalar len = Length();
            _vector4[0] /= len;
            _vector4[1] /= len;
            _vector4[2] /= len;
            _vector4[3] /= len;
        }

        public static Vector4 normalize(Vector4 v)
        {
            Vector4 rv = new Vector4();
            Scalar len = v.Length();
            rv._Vector4[0] = v._Vector4[0] /= len;
            rv._Vector4[1] = v._Vector4[1] /= len;
            rv._Vector4[2] = v._Vector4[2] /= len;
            rv._Vector4[3] = v._Vector4[3] /= len;
            return rv;
        }

        public static Vector3 homogenize(Vector4 v)
        {
            Vector3 val;

            if (v._Vector4[3] != 0)
            {
                val = new Vector3(v._Vector4[0] / v._Vector4[3], v._Vector4[1] / v._Vector4[3],
                               v._Vector4[2] / v._Vector4[3]);
                return val;
            }
            else
            {
                val = new Vector3(v._Vector4[0], v._Vector4[1], v._Vector4[2]);
                return val;
            }
        }

        public void print()
        {
            string content = "[ ";
            content = content + _vector4[0] + " " + _vector4[1] + " "
                      + _vector4[2] + " " + _vector4[3] + " ]\n";
            Console.WriteLine(content);
        }

        // operator functions
        public static Vector4 operator +(Vector4 a, Vector4 b)
        {
            Vector4 temp = new Vector4();
            temp._Vector4[0] = a._Vector4[0] + b._Vector4[0];
            temp._Vector4[1] = a._Vector4[1] + b._Vector4[1];
            temp._Vector4[2] = a._Vector4[2] + b._Vector4[2];
            temp._Vector4[3] = a._Vector4[3] + b._Vector4[3];
            return temp;
        }

        public static Vector4 operator -(Vector4 v)
        {
            Vector4 temp = new Vector4();
            temp._Vector4[0] = -v._Vector4[0];
            temp._Vector4[1] = -v._Vector4[1];
            temp._Vector4[2] = -v._Vector4[2];
            temp._Vector4[3] = -v._Vector4[3];
            return temp;
        }

        public static Vector4 operator -(Vector4 a, Vector4 b)
        {
            Vector4 temp = new Vector4();
            temp._Vector4[0] = a._Vector4[0] - b._Vector4[0];
            temp._Vector4[1] = a._Vector4[1] - b._Vector4[1];
            temp._Vector4[2] = a._Vector4[2] - b._Vector4[2];
            temp._Vector4[3] = a._Vector4[3] - b._Vector4[3];
            return temp;
        }

        public static Vector4 operator *(Vector4 a, Vector4 b)
        {
            Vector4 temp = new Vector4();
            temp._Vector4[0] = a._Vector4[0] * b._Vector4[0];
            temp._Vector4[1] = a._Vector4[1] * b._Vector4[1];
            temp._Vector4[2] = a._Vector4[2] * b._Vector4[2];
            temp._Vector4[3] = a._Vector4[3] * b._Vector4[3];
            return temp;
        }

        public static Vector4 operator *(Scalar s, Vector4 b)
        {
            Vector4 temp = new Vector4();
            temp._Vector4[0] = s * b._Vector4[0];
            temp._Vector4[1] = s * b._Vector4[1];
            temp._Vector4[2] = s * b._Vector4[2];
            temp._Vector4[3] = s * b._Vector4[3];
            return temp;
        }

        public static Vector4 operator *(Vector4 a, Scalar s)
        {
            Vector4 temp = new Vector4();
            temp._Vector4[0] = a._Vector4[0] * s;
            temp._Vector4[1] = a._Vector4[1] * s;
            temp._Vector4[2] = a._Vector4[2] * s;
            temp._Vector4[3] = a._Vector4[3] * s;
            return temp;
        }

        public static Vector4 operator /(Vector4 a, Vector4 b)
        {
            Vector4 temp = new Vector4();
            temp._Vector4[0] = a._Vector4[0] / b._Vector4[0];
            temp._Vector4[1] = a._Vector4[1] / b._Vector4[1];
            temp._Vector4[2] = a._Vector4[2] / b._Vector4[2];
            temp._Vector4[3] = a._Vector4[3] / b._Vector4[3];
            return temp;
        }

        public static Vector4 operator /(Scalar s, Vector4 b)
        {
            Vector4 temp = new Vector4();
            temp._Vector4[0] = s / b._Vector4[0];
            temp._Vector4[1] = s / b._Vector4[1];
            temp._Vector4[2] = s / b._Vector4[2];
            temp._Vector4[3] = s / b._Vector4[3];
            return temp;
        }

        public static Vector4 operator /(Vector4 a, Scalar s)
        {
            Vector4 temp = new Vector4();
            temp._Vector4[0] = a._Vector4[0] / s;
            temp._Vector4[1] = a._Vector4[1] / s;
            temp._Vector4[2] = a._Vector4[2] / s;
            temp._Vector4[3] = a._Vector4[3] / s;
            return temp;
        }

        public static bool operator ==(Vector4 a, Vector4 b)
        {
            if (a._Vector4[0] != b._Vector4[0]) return false;
            if (a._Vector4[1] != b._Vector4[1]) return false;
            if (a._Vector4[2] != b._Vector4[2]) return false;
            if (a._Vector4[3] != b._Vector4[3]) return false;
            return true;
        }

        public static bool operator !=(Vector4 a, Vector4 b)
        {
            return !(a == b);
        }

        public override bool Equals(Object obj)
        {
            return obj is Vector4 && this == (Vector4)obj;
        }

        public override int GetHashCode()
        {
            return _vector4.GetHashCode();
        }
    }

    #endregion
    #region Vector2i Vector3i Vector4i
    //
    // Vector2i - this is more a container than an actual vector type.
    //  Normalizing and things of this nature don't make a ton of sense on integer type vectors.
    //
    [Serializable]
    public class Vector2i : IVector
    {
        // data member
        private int[] _vector2 = new int[2];

        #region Constructors
        public Vector2i()
        {
            Zero();
        }

        public Vector2i(int[] t)
        {
            _vector2[0] = t[0];
            _vector2[1] = t[1];
        }

        public Vector2i(Vector2i v)
        {
            _vector2[0] = v._Vector2[0];
            _vector2[1] = v._Vector2[1];
        }

        public Vector2i(int x, int y)
        {
            _vector2[0] = x;
            _vector2[1] = y;
        }
        #endregion

        // property
        public int[] _Vector2
        {
            get { return this._vector2; }
            set { this._vector2 = value; }
        }

        public int this[int index]
        {
            get { return _vector2[index]; }
            set
            {
                if ((index >= 0) && (index < 2))
                    _vector2[index] = value;
                else
                    throw (new IndexOutOfRangeException());
            }
        }

        public int x
        {
            get { return _vector2[0]; }
            set { _vector2[0] = value; }
        }
        public int y
        {
            get { return _vector2[1]; }
            set { _vector2[1] = value; }
        }

        // public methods
        public int[] getValue()
        {
            int[] rs = new int[2];
            rs[0] = _vector2[0];
            rs[1] = _vector2[1];

            return rs;
        }

        public void setValue(int v0, int v1)
        {
            _vector2[0] = v0;
            _vector2[1] = v1;
        }

        #region IVector Members
        public void Zero()
        {
            _vector2[0] = 0;
            _vector2[1] = 0;
        }

        public Scalar Length()
        {
            return (Scalar)System.Math.Sqrt((double)this.LengthSquared());
        }

        public float LengthSquared()
        {
            Scalar r;
            r = _vector2[0] * _vector2[0] + _vector2[1] * _vector2[1];
            return r;
        }
        #endregion
    }

    //
    // Vector3i - this is a container more than it is an actual vector type
    //
    [Serializable]
    public class Vector3i : IVector
    {
        // data member
        private int[] _vector3 = new int[3];

        #region Constructors
        public Vector3i()
        {
            Zero();
        }

        public Vector3i(int[] t)
        {
            _vector3[0] = t[0];
            _vector3[1] = t[1];
            _vector3[2] = t[2];
        }

        public Vector3i(Vector3i v)
        {
            _vector3[0] = v._Vector3[0];
            _vector3[1] = v._Vector3[1];
            _vector3[2] = v._Vector3[2];
        }

        public Vector3i(int x, int y, int z)
        {
            _vector3[0] = x;
            _vector3[1] = y;
            _vector3[2] = z;
        }
        #endregion

        // property
        public int[] _Vector3
        {
            get { return this._vector3; }
            set { this._vector3 = value; }
        }

        public int this[int index]
        {
            get { return _vector3[index]; }
            set
            {
                if ((index >= 0) && (index < 3))
                    _vector3[index] = value;
                else
                    throw (new IndexOutOfRangeException());
            }
        }

        public int x
        {
            get { return _vector3[0]; }
            set { _vector3[0] = value; }
        }
        public int y
        {
            get { return _vector3[1]; }
            set { _vector3[1] = value; }
        }
        public int z
        {
            get { return _vector3[2]; }
            set { _vector3[2] = value; }
        }

        // public methods
        public int[] getValue()
        {
            int[] rs = new int[3];
            rs[0] = _vector3[0];
            rs[1] = _vector3[1];
            rs[2] = _vector3[2];

            return rs;
        }

        public void setValue(int v0, int v1, int v2)
        {
            _vector3[0] = v0;
            _vector3[1] = v1;
            _vector3[2] = v2;
        }

        #region IVector Members
        public void Zero()
        {
            _vector3[0] = 0;
            _vector3[1] = 0;
            _vector3[2] = 0;
        }

        public Scalar Length()
        {
            return (Scalar)System.Math.Sqrt((double)this.LengthSquared());
        }

        public Scalar LengthSquared()
        {
            Scalar r;
            r = _vector3[0] * _vector3[0] + _vector3[1] * _vector3[1] + _vector3[2] * _vector3[2];
            return r;
        }
        #endregion
    }

    //
    // Vector4i - this is more of a container than a vector type
    //
    [Serializable]
    public class Vector4i : IVector
    {
        // data memeber
        private int[] _vector4 = new int[4];

        #region Constructors
        public Vector4i()
        {
            Zero();
        }

        public Vector4i(int[] t)
        {
            _vector4[0] = t[0];
            _vector4[1] = t[1];
            _vector4[2] = t[2];
            _vector4[3] = t[3];
        }

        public Vector4i(Vector4i v)
        {
            _vector4[0] = v._Vector4[0];
            _vector4[1] = v._Vector4[1];
            _vector4[2] = v._Vector4[2];
            _vector4[3] = v._Vector4[3];
        }

        public Vector4i(int x, int y, int z, int w)
        {
            _vector4[0] = x;
            _vector4[1] = y;
            _vector4[2] = z;
            _vector4[3] = w;
        }
        #endregion

        // property
        public int[] _Vector4
        {
            get { return this._vector4; }
            set { this._vector4 = value; }
        }

        public int this[int index]
        {
            get { return _vector4[index]; }
            set
            {
                if ((index >= 0) && (index < 4))
                    _vector4[index] = value;
                else
                    throw (new IndexOutOfRangeException());
            }
        }

        public int x
        {
            get { return _vector4[0]; }
            set { _vector4[0] = value; }
        }
        public int y
        {
            get { return _vector4[1]; }
            set { _vector4[1] = value; }
        }
        public int z
        {
            get { return _vector4[2]; }
            set { _vector4[2] = value; }
        }
        public int w
        {
            get { return _vector4[3]; }
            set { _vector4[3] = value; }
        }

        // public methods
        public int[] getValue()
        {
            int[] rs = new int[4];
            rs[0] = _vector4[0];
            rs[1] = _vector4[1];
            rs[2] = _vector4[2];
            rs[3] = _vector4[3];

            return rs;
        }

        #region IVector Members
        public void Zero()
        {
            _vector4[0] = 0;
            _vector4[1] = 0;
            _vector4[2] = 0;
            _vector4[3] = 0;
        }

        public Scalar Length()
        {
            return (Scalar)System.Math.Sqrt((double)this.LengthSquared());
        }

        public Scalar LengthSquared()
        {
            Scalar r;
            r = _vector4[0] * _vector4[0] + _vector4[1] * _vector4[1]
                + _vector4[2] * _vector4[2] + _vector4[3] * _vector4[3];
            return r;
        }
        #endregion
    }

    #endregion

    #region Vector2b Vector3b Vector4b
    //
    // Vector2b - this is more a container than an actual vector type.
    //  Normalizing and things of this nature don't make a ton of sense on boolean type vectors.
    //
    [Serializable]
    public class Vector2b : IVector
    {
        // data member
        private bool[] _vector2 = new bool[2];

        // constructors
        public Vector2b()
        {
            Zero();
        }

        public Vector2b(bool[] t)
        {
            _vector2[0] = t[0];
            _vector2[1] = t[1];
        }

        public Vector2b(Vector2b v)
        {
            _vector2[0] = v._Vector2[0];
            _vector2[1] = v._Vector2[1];
        }

        public Vector2b(bool x, bool y)
        {
            _vector2[0] = x;
            _vector2[1] = y;
        }

        // property
        public bool[] _Vector2
        {
            get { return this._vector2; }
            set { this._vector2 = value; }
        }

        public bool this[int index]
        {
            get { return _vector2[index]; }
            set
            {
                if ((index >= 0) && (index < 2))
                    _vector2[index] = value;
                else
                    throw (new IndexOutOfRangeException());
            }
        }

        public bool x
        {
            get { return _vector2[0]; }
            set { _vector2[0] = value; }
        }
        public bool y
        {
            get { return _vector2[1]; }
            set { _vector2[1] = value; }
        }

        // public methods
        public bool[] getValue()
        {
            bool[] rs = new bool[2];
            rs[0] = _vector2[0];
            rs[1] = _vector2[1];

            return rs;
        }

        public int[] getIntValue()
        {
            int[] rs = new int[2];
            rs[0] = (_vector2[0]) ? 1 : 0;
            rs[1] = (_vector2[1]) ? 1 : 0;

            return rs;
        }

        public void setValue(bool v0, bool v1)
        {
            _vector2[0] = v0;
            _vector2[1] = v1;
        }

        public void Zero()
        {
            _vector2[0] = false;
            _vector2[1] = false;
        }

        #region IVector Members
        float IVector.Length()
        {
            throw new NotImplementedException();
        }

        float IVector.LengthSquared()
        {
            throw new NotImplementedException();
        }
        #endregion
    }

    //
    // Vector3b - this is a container more than it is an actual vector type
    //
    [Serializable]
    public class Vector3b : IVector
    {
        // data member
        private bool[] _vector3 = new bool[3];

        // constructors
        public Vector3b()
        {
            Zero();
        }

        public Vector3b(bool[] t)
        {
            _vector3[0] = t[0];
            _vector3[1] = t[1];
            _vector3[2] = t[2];
        }

        public Vector3b(Vector3b v)
        {
            _vector3[0] = v._Vector3[0];
            _vector3[1] = v._Vector3[1];
            _vector3[2] = v._Vector3[2];
        }

        public Vector3b(bool x, bool y, bool z)
        {
            _vector3[0] = x;
            _vector3[1] = y;
            _vector3[2] = z;
        }

        // property
        public bool[] _Vector3
        {
            get { return this._vector3; }
            set { this._vector3 = value; }
        }

        public bool this[int index]
        {
            get { return _vector3[index]; }
            set
            {
                if ((index >= 0) && (index < 3))
                    _vector3[index] = value;
                else
                    throw (new IndexOutOfRangeException());
            }
        }

        public bool x
        {
            get { return _vector3[0]; }
            set { _vector3[0] = value; }
        }
        public bool y
        {
            get { return _vector3[1]; }
            set { _vector3[1] = value; }
        }
        public bool z
        {
            get { return _vector3[2]; }
            set { _vector3[2] = value; }
        }

        // public methods
        public bool[] getValue()
        {
            bool[] rs = new bool[3];
            rs[0] = _vector3[0];
            rs[1] = _vector3[1];
            rs[2] = _vector3[2];

            return rs;
        }

        public int[] getIntValue()
        {
            int[] rs = new int[3];
            rs[0] = (_vector3[0]) ? 1 : 0;
            rs[1] = (_vector3[1]) ? 1 : 0;
            rs[2] = (_vector3[2]) ? 1 : 0;

            return rs;
        }

        public void setValue(bool v0, bool v1, bool v2)
        {
            _vector3[0] = v0;
            _vector3[1] = v1;
            _vector3[2] = v2;
        }

        public void Zero()
        {
            _vector3[0] = false;
            _vector3[1] = false;
            _vector3[2] = false;
        }

        #region IVector Members
        float IVector.Length()
        {
            throw new NotImplementedException();
        }

        float IVector.LengthSquared()
        {
            throw new NotImplementedException();
        }
        #endregion
    }

    //
    // Vector4b - this is more of a container than a vector type
    //
    [Serializable]
    public class Vector4b : IVector
    {
        // data memeber
        private bool[] _vector4 = new bool[4];

        // copnstructors
        public Vector4b()
        {
            Zero();
        }

        public Vector4b(bool[] t)
        {
            _vector4[0] = t[0];
            _vector4[1] = t[1];
            _vector4[2] = t[2];
            _vector4[3] = t[3];
        }

        public Vector4b(Vector4b v)
        {
            _vector4[0] = v._Vector4[0];
            _vector4[1] = v._Vector4[1];
            _vector4[2] = v._Vector4[2];
            _vector4[3] = v._Vector4[3];
        }

        public Vector4b(bool x, bool y, bool z, bool w)
        {
            _vector4[0] = x;
            _vector4[1] = y;
            _vector4[2] = z;
            _vector4[3] = w;
        }

        // property
        public bool[] _Vector4
        {
            get { return this._vector4; }
            set { this._vector4 = value; }
        }

        public bool this[int index]
        {
            get { return _vector4[index]; }
            set
            {
                if ((index >= 0) && (index < 4))
                    _vector4[index] = value;
                else
                    throw (new IndexOutOfRangeException());
            }
        }

        public bool x
        {
            get { return _vector4[0]; }
            set { _vector4[0] = value; }
        }
        public bool y
        {
            get { return _vector4[1]; }
            set { _vector4[1] = value; }
        }
        public bool z
        {
            get { return _vector4[2]; }
            set { _vector4[2] = value; }
        }
        public bool w
        {
            get { return _vector4[3]; }
            set { _vector4[3] = value; }
        }

        // public methods
        public bool[] getValue()
        {
            bool[] rs = new bool[4];
            rs[0] = _vector4[0];
            rs[1] = _vector4[1];
            rs[2] = _vector4[2];
            rs[3] = _vector4[3];

            return rs;
        }

        public int[] getIntValue()
        {
            int[] rs = new int[4];
            rs[0] = (_vector4[0]) ? 1 : 0;
            rs[1] = (_vector4[1]) ? 1 : 0;
            rs[2] = (_vector4[2]) ? 1 : 0;
            rs[3] = (_vector4[3]) ? 1 : 0;

            return rs;
        }

        public void Zero()
        {
            _vector4[0] = false;
            _vector4[1] = false;
            _vector4[2] = false;
            _vector4[3] = false;
        }

        #region IVector Members
        float IVector.Length()
        {
            throw new NotImplementedException();
        }

        float IVector.LengthSquared()
        {
            throw new NotImplementedException();
        }
        #endregion
    }

    #endregion
}
